package com.zx.system.block.listener;

import com.zx.core.constant.CacheConstants;
import com.zx.redis.block.service.RedisBlockService;
import com.zx.system.block.event.DictDataChangeEvent;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.HashSet;
import java.util.Set;

/**
 * 字典数据缓存清理监听器
 * 监听字典数据变更事件，清理相关缓存
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class DictDataCacheEvictListener {

    private final RedisBlockService redisBlockService;

    /**
     * 处理字典数据变更事件
     * 当收到字典数据变更事件时，清理相关缓存
     *
     * @param event 字典数据变更事件
     */
    @EventListener
    public void handleDictDataChangeEvent(DictDataChangeEvent event) {
        try {
            log.info("收到字典数据变更事件: dictType={}, operation={}", event.getDictType(), event.getOperation());

            // 清理指定字典类型的VO缓存
            String voCacheKey = CacheConstants.DICT_DATA_KEY + event.getDictType();
            redisBlockService.deleteObject(voCacheKey);
            log.info("已清理字典类型[{}]的VO缓存", event.getDictType());

            // 清理指定字典类型的DTO缓存
            String dtoCacheKey = CacheConstants.DICT_DATA_KEY + "dto:" + event.getDictType();
            redisBlockService.deleteObject(dtoCacheKey);
            log.info("已清理字典类型[{}]的DTO缓存", event.getDictType());

            // 清理指定字典类型的基础数据缓存（VO和DTO共享的基础数据）
            String baseCacheKey = CacheConstants.DICT_DATA_KEY + "base:" + event.getDictType();
            redisBlockService.deleteObject(baseCacheKey);
            log.info("已清理字典类型[{}]的基础数据缓存", event.getDictType());

            // 清理批量缓存（包括VO和DTO的批量缓存）
            clearBatchDictDataCaches(event.getDictType());
        } catch (Exception e) {
            log.error("处理字典数据变更事件时发生错误", e);
        }
    }

    /**
     * 清理可能包含指定字典类型的批量缓存
     *
     * @param dictType 字典类型
     */
    @SuppressWarnings("unchecked")
    private void clearBatchDictDataCaches(String dictType) {
        try {
            // 查找所有可能包含该字典类型的批量缓存键
            Set<String> keys = (Set<String>) redisBlockService.redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
                Set<String> result = new HashSet<>();
                // 匹配所有批量缓存键
                Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions()
                        .match(CacheConstants.DICT_DATA_KEY + "*batch*")
                        .count(1000)
                        .build());

                while (cursor.hasNext()) {
                    result.add(new String(cursor.next()));
                }
                cursor.close();
                return result;
            });

            // 删除匹配的缓存键
            if (!CollectionUtils.isEmpty(keys)) {
                redisBlockService.deleteObject(keys);
                log.info("已清理包含字典类型[{}]的{}个批量缓存", dictType, keys.size());
            }
        } catch (Exception e) {
            log.error("清理批量字典数据缓存时发生错误", e);
        }
    }
}